#include "TcpServer.hpp"
#include <memory>
#include "Protocol.hpp"
#include <signal.h>
#include "Daemon.hpp"

using namespace ns_tcpserver;
using namespace ns_protocol;

static void Usage(const std::string& proc)
{
    std::cout << "\nUsage: " << proc << " port\n" << std::endl;
}

static Response calculatorHelper(const Request& req)
{
    Response resp(0, 0, req._x, req._y, req._op);
    switch (req._op)
    {
    case '+':
        resp._result = req._x + req._y;
        break;
    case '-':
        resp._result = req._x - req._y;
        break;
    case '*':
        resp._result = req._x * req._y;
        break;
    case '/':
        if (0 == req._y)
        {
            resp._code = 1;
        }
        else
        {
            resp._result = req._x / req._y;
        }
        break;
    case '%':
        if (0 == req._y)
        {
            resp._code = 2;
        }
        else
        {
            resp._result = req._x % req._y;
        }
        break;
    default:
        resp._code = 3;
        break;
    }
    return resp;
}

void calculator(int sock)
{
    std::string inbuffer;
    while (true)
    {
        //1.读取数据
        bool res = Recv(sock, &inbuffer);//在这里读到了一个请求
        if (!res)
        {
            break;
        }
        // std::cout << "begin: inbuffer: " << inbuffer.c_str() << std::endl;
        //2.解析报文，保证得到一个完整的报文
        std::string package = Decode(inbuffer);

        if (package.empty())
        {
            continue;
        }
        // std::cout << "end: inbuffer: " << inbuffer.c_str() << std::endl;
        // std::cout << "package: " << package.c_str() << std::endl;
        logMessage(NORMAL, "%s", package.c_str());
        
        //3.保证该报文是一个完整的报文
        Request req;
        //4.反序列化，字节流->结构化
        req.Deserialized(package);//反序列化
        //5.业务逻辑
        Response resp = calculatorHelper(req);
        //6.序列化
        std::string respString = resp.Serialize();//对计算结果进行序列化
        //7.添加长度信息，形成一个完整的报文
        //"length\r\ncode result\r\n"
        // std::cout << "respString: " << respString.c_str() << std::endl;
        respString = Encode(respString);
        // std::cout << "encode: respString: " << respString.c_str() << std::endl;
        //8.
        Send(sock, respString);


    }
}

// void handler(int signo)
// {
//     std::cout << "get a signo: " << signo << std::endl;
//     exit(0);
// }

// ./CalServer port
int main(int argc, char* argv[])
{
    if (argc != 2)
    {
        Usage(argv[0]);
        exit(1);
    }

    //server在编写的时候，要有较为严谨的判断逻辑
    //一般服务器，都是要忽略SIGPIPE信号的，防止在运行中出现非法写入的问题
    // signal(SIGPIPE, SIG_IGN);
    MyDaemon();

    std::unique_ptr<TcpServer> server(new TcpServer(atoi(argv[1])));
    server->BindService(calculator);
    server->Start();

    // Request req(123, 456, '+');
    // std::string s = req.Serialize();
    // std::cout << s << std::endl;

    // Request temp;
    // temp.Deserialized(s);
    // std::cout << temp._x << std::endl;
    // std::cout << temp._op << std::endl;
    // std::cout << temp._y << std::endl;

    return 0;
}